# We assume that the utilities from RISC-V cross-compiler (i.e., riscv64-unknown-elf-gcc and etc.)
# are in your system PATH. To check if your environment satisfies this requirement, simple use 
# `which` command as follows:
# $ which riscv64-unknown-elf-gcc
# if you have an output path, your environment satisfy our requirement.

# ---------------------	macros --------------------------
CROSS_PREFIX = riscv64-unknown-elf-

OBJ_DIR = obj
BINDIR	:= bin
CC = $(CROSS_PREFIX)gcc
LD            := $(CC)
AR = $(CROSS_PREFIX)ar
RANLIB        := riscv64-unknown-elf-ranlib


ifneq (,)
  march := -march=
  is_32bit := $(findstring 32,$(march))
  mabi := -mabi=$(if $(is_32bit),ilp32,lp64)
endif

# march:= -march=rv64g
# mabi := -mabi=lp64d

LIBS          := -lgcc -L $(OBJ_DIR)/ 
#ALL_APPS := $(notdir $(basename $(wildcard apps/*.c)))


src_dir      := .
sprojs_enabled :=  include  kernel kernel/machine
sprojs_include := -I. $(addprefix -I$(src_dir)/, $(sprojs_enabled)) 


CFLAGS        := -Wall  -D__NO_INLINE__ -mcmodel=medany -O2 -std=gnu99 -Wno-unused -Wno-attributes -fno-delete-null-pointer-checks -fno-PIE   $(march) $(mabi)
COMPILE       := $(CC) -MMD -MP -Wno-stringop-truncation $(CFLAGS)  $(sprojs_include)

LDFLAGS       :=  -Wl,--build-id=none -nostartfiles -nostdlib -static $(LDFLAGS) $(march) $(mabi)
LINK          := $(LD) $(LDFLAGS)
# ---------------------	objectives -----------------------

MACHINE_OBJS = kernel/machine/minit.o  kernel/machine/htif.o   kernel/machine/mtrap.o  kernel/machine/finisher.o  kernel/machine/fdt.o  
MACHINE_DESTS := $(addprefix $(OBJ_DIR)/, $(MACHINE_OBJS)) # obj/kernel/machine/mentry.o 
MACHINE_ASM_OBJS = kernel/machine/mentry.o
MACHINE_ASM_OBJS_DESTS =$(addprefix $(OBJ_DIR)/, $(MACHINE_ASM_OBJS))


KERNEL_OBJS = kernel/kernel.o  kernel/file.o  kernel/console.o   kernel/memory.o   kernel/frontend.o kernel/mmap.o  kernel/proc.o kernel/trap.o kernel/spinlock.o \
kernel/elf.o  kernel/syscall.o kernel/sleeplock.o  kernel/fs_sysfile.o  kernel/fs.o  kernel/bio.o  kernel/fs_disk.o kernel/fs_file.o kernel/sound.o kernel/fat32.o
KERNEL_DESTS := $(addprefix $(OBJ_DIR)/, $(KERNEL_OBJS))
KERNEL_ASM_OBJS = kernel/userTrapEntry.o kernel/kernelTrapEntry.o kernel/switch.o
KERNEL_ASM_OBJS_DESTS = $(addprefix $(OBJ_DIR)/, $(KERNEL_ASM_OBJS))


UTIL_OBJS = util/snprintf.o util/string.o 
UTIL_DESTS := $(addprefix $(OBJ_DIR)/, $(UTIL_OBJS))
UTIL_ASM_OBJS = 
UTIL_ASM_OBJS_DESTS =

USER_OBJS = apps/app_invalide_inst apps/app_helloworld apps/app_fork  apps/app_badaddr apps/app_page_fault_1   apps/app_page_fault_2 \
apps/app_wait apps/app_exec apps/app_loop  apps/sh apps/init

USER_DESTS := $(addprefix $(OBJ_DIR)/, $(USER_OBJS)) 


link_libs =  -lmachine  -lkernel -lutil

# ---------------------	make targets ---------------------
all : os objdump 
	cd ./userlib && make
	cd ./apps && make
	cd ./sound_card_sim && make
	# cd ./mkfs && make

grade: clean all
	python3 grade.py

.PHONY : all, grade


$(OBJ_DIR):
	@test -d $(OBJ_DIR) || mkdir $(OBJ_DIR)
	@test -d $(OBJ_DIR)/apps || mkdir $(OBJ_DIR)/apps
	@test -d $(OBJ_DIR)/kernel || mkdir $(OBJ_DIR)/kernel
	@test -d $(OBJ_DIR)/kernel/machine || mkdir $(OBJ_DIR)/kernel/machine
	@test -d $(OBJ_DIR)/util || mkdir $(OBJ_DIR)/util
$(BINDIR):
	@test -d $(BINDIR) || mkdir $(BINDIR)

$(USER_DESTS): $(OBJ_DIR)/% : ./%.c
	$(CC)  $< -o $@ -I include -L libuser -luser

apps: $(OBJ_DIR) $(USER_DESTS)
	@echo  "APPS compiled"
#------------------ os -----------------------

os : $(OBJ_DIR)  $(OBJ_DIR)/thinos
	@echo  "thinos compiled"

$(OBJ_DIR)/thinos : $(OBJ_DIR)/kernel/kernel.o  $(OBJ_DIR)/libmachine.a   $(OBJ_DIR)/libutil.a  $(OBJ_DIR)/libkernel.a
	$(LINK) -o $@ $<  $(LIBS) $(link_libs) -T kernel/kernel.lds


# -------------- libs---------------------------------
#machine
 $(OBJ_DIR)/libmachine.a: $(MACHINE_DESTS) $(MACHINE_ASM_OBJS_DESTS)
	$(AR) rcv -o $@ $^
	$(RANLIB) $@

$(MACHINE_DESTS): $(OBJ_DIR)/%.o : %.c
	$(COMPILE) -c $< -o $@


$(MACHINE_ASM_OBJS_DESTS): $(OBJ_DIR)/%.o : %.S
	$(COMPILE) -c $< -o $@

#kernel 
 $(OBJ_DIR)/libkernel.a: $(KERNEL_ASM_OBJS_DESTS)  $(KERNEL_DESTS)
	$(AR) rcv -o $@ $^
	$(RANLIB) $@

$(KERNEL_DESTS): $(OBJ_DIR)/%.o : %.c
	$(COMPILE) -c $< -o $@


$(KERNEL_ASM_OBJS_DESTS): $(OBJ_DIR)/%.o : %.S
	$(COMPILE) -c $< -o $@

#util
 $(OBJ_DIR)/libutil.a: $(UTIL_DESTS) $(UTIL_ASM_OBJS_DESTS)
	$(AR) rcv -o $@ $^
	$(RANLIB) $@

$(UTIL_DESTS): $(OBJ_DIR)/%.o : %.c
	$(COMPILE) -c $< -o $@


$(UTIL_ASM_OBJS_DESTS): $(OBJ_DIR)/%.o : %.S
	$(COMPILE) -c $< -o $@



test:
	echo  $(ALL_APPS)


objdump:
	riscv64-unknown-elf-objdump -d obj/thinos > thinos_dump


cscope:
	find ./ -name "*.c" > cscope.files
	find ./ -name "*.h" >> cscope.files
	find ./ -name "*.S" >> cscope.files
	find ./ -name "*.lds" >> cscope.files
	cscope -bqk

clean:
	rm -fr ${OBJ_DIR} objdump
	rm -fr ${SFSROOT}
	rm -fr ${BINDIR}
	cd ./userlib && make clean

# create sfs.img
UPROGS=\
	$U/_cat\
	$U/_echo\
	$U/_forktest\
	$U/_grep\
	$U/_init\
	$U/_kill\
	$U/_ln\
	$U/_ls\
	$U/_mkdir\
	$U/_rm\
	$U/_sh\
	$U/_stressfs\
	$U/_usertests\
	$U/_grind\
	$U/_wc\
	$U/_zombie\

fs.img: mkfs/mkfs  $(UPROGS)
	dd if=/dev/zero of=$@ bs=1kB count=480 
	mkfs/mkfs fs.img  $(UPROGS)

mkfs/mkfs: mkfs/mkfs.c 
	gcc -Werror -Wall -I. -o mkfs/mkfs mkfs/mkfs.c

